package com.app.twth.ui.printer;

import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.usb.UsbManager;
import android.os.Handler;
import android.os.Message;
import android.view.View;

import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.databinding.library.baseAdapters.BR;

import com.app.twth.R;
import com.app.twth.app.Constant;
import com.app.twth.app.MyApplication;
import com.app.twth.base.BaseActivity;
import com.app.twth.databinding.ActivityPrinterBinding;
import com.app.twth.ui.mine.version.VersionViewModel;
import com.app.twth.utils.ToastUtil;
import com.smart.command.CpclCommand;
import com.smart.command.LabelCommand;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Vector;

/**
 * Created by admin on 2024/5/7.
 * Description:
 * Encoding: utf-8
 */
public class PrinterActivity extends BaseActivity<ActivityPrinterBinding, VersionViewModel> {
    private String TAG = getClass().getSimpleName();
    ArrayList<String> per = new ArrayList<>();
    private static final int REQUEST_CODE = 0x004;

    private static final int CONN_MOST_DEVICES = 0x11;
    private static final int CONN_PRINTER = 0x12;

    /**
     * Connection status disconnected
     */
    private static final int CONN_STATE_DISCONN = 0x007;
    /**
     * Use printer command error
     */
    private static final int PRINTER_COMMAND_ERROR = 0x008;

    private String[] permissions = {
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.BLUETOOTH
    };

    private ThreadPool threadPool;

    @Override
    protected void initListener() {

    }

    @Override
    protected int initViewModelId() {
        return BR.viewModel;
    }

    @Override
    protected void initData() {
        setLayoutBottomGone();

        checkPermission();
        requestPermission();
        IntentFilter filter = new IntentFilter();
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        filter.addAction(DeviceConnFactoryManager.ACTION_QUERY_PRINTER_STATE);
        filter.addAction(DeviceConnFactoryManager.ACTION_CONN_STATE);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        registerReceiver(receiver, filter);
    }

    @Override
    protected String setTitle() {
        return "Printer";
    }

    private void checkPermission() {
        for (String permission : permissions) {
            if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(this, permission)) {
                per.add(permission);
            }
        }
    }

    private void requestPermission() {
        if (per.size() > 0) {
            String[] p = new String[per.size()];
            ActivityCompat.requestPermissions(this, per.toArray(p), REQUEST_CODE);
        }
    }

    /**
     * Bluetooth connectivity
     */
    public void btnBluetoothConn(View view) {
        startActivityForResult(new Intent(this, BleDeviceActivity.class), Constant.BLUETOOTH_REQUEST_CODE);
    }

    public void btnWifiConn(View view) {
        WifiParameterConfigDialog wifiParameterConfigDialog = new WifiParameterConfigDialog(this, new WifiParameterConfigDialog.WifiConfigCallback() {
            @Override
            public void callback(String ip, int port) {
                if (port == 9101) {
                    MyApplication.printerService.connectWifi(ip, port);
                    return;
                }

                new DeviceConnFactoryManager.Build()
                        //Set bluetooth mac address
                        .setConnectMethod(DeviceConnFactoryManager.CONN_METHOD.WIFI)
                        .setIp(ip)
                        .setPort(port)
                        .build();
                //Open port
                threadPool = ThreadPool.getInstantiation();
                threadPool.addTask(() -> DeviceConnFactoryManager.getDeviceConnFactoryManager().openPort());
            }
        });
        wifiParameterConfigDialog.show();
    }

    /**
     * Print face sheet
     *
     * @param view
     */
    public void btnCpclPrint(View view) {
        if (DeviceConnFactoryManager.getDeviceConnFactoryManager() == null ||
                !DeviceConnFactoryManager.getDeviceConnFactoryManager().getConnState()) {
            ToastUtil.showToast(getString(R.string.str_cann_printer));
            return;
        }
        threadPool = ThreadPool.getInstantiation();
        threadPool.addTask(() -> printPDF());
//        threadPool.addTask(() -> sendCpcl());
    }


    /**
     * Disconnect
     *
     * @param view
     */
    public void btnDisConn(View view) {
        MyApplication.printerService.disconnect();
//        firstInit();
        if (DeviceConnFactoryManager.getDeviceConnFactoryManager() == null ||
                !DeviceConnFactoryManager.getDeviceConnFactoryManager().getConnState()) {
            ToastUtil.showToast(getString(R.string.str_cann_printer));
            return;
        }
        mHandler.obtainMessage(CONN_STATE_DISCONN).sendToTarget();
    }

    private BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            switch (action) {
                case DeviceConnFactoryManager.ACTION_CONN_STATE:
                    int state = intent.getIntExtra(DeviceConnFactoryManager.STATE, -1);
                    switch (state) {
                        case DeviceConnFactoryManager.CONN_STATE_DISCONNECT:
                            binding.tvConnState.setText(getString(R.string.str_conn_state_disconnect));
                            break;
                        case DeviceConnFactoryManager.CONN_STATE_CONNECTING:
                            binding.tvConnState.setText(getString(R.string.str_conn_state_connecting));
                            break;
                        case DeviceConnFactoryManager.CONN_STATE_CONNECTED:
                            binding.tvConnState.setText(getString(R.string.str_conn_state_connected) + "\n" + getConnDeviceInfo());
                            MyApplication.printerService.mIsConnected = false;
                            firstInit();
                            break;
                        case DeviceConnFactoryManager.CONN_STATE_FAILED:
                            ToastUtil.showToast(getString(R.string.str_conn_fail));
                            binding.tvConnState.setText(getString(R.string.str_conn_state_disconnect));
                            break;
                        default:
                            break;
                    }
                    break;
                case DeviceConnFactoryManager.ACTION_QUERY_PRINTER_STATE:

                    break;
                default:
                    break;
            }
        }
    };

    private String getConnDeviceInfo() {
        String str = "";
        DeviceConnFactoryManager deviceConnFactoryManager = DeviceConnFactoryManager.getDeviceConnFactoryManager();
        if (deviceConnFactoryManager != null
                && deviceConnFactoryManager.getConnState()) {
            if (deviceConnFactoryManager.getConnMethod() == DeviceConnFactoryManager.CONN_METHOD.BLUETOOTH) {
                str += "BLUETOOTH\n";
                str += "MacAddress: " + deviceConnFactoryManager.getMacAddress();
            } else if (deviceConnFactoryManager.getConnMethod() == DeviceConnFactoryManager.CONN_METHOD.WIFI) {
                str += "WIFI\n";
                str += "ip: " + deviceConnFactoryManager.getIp() + "\n";
                str += "port: " + deviceConnFactoryManager.getPort();
            }
        }
        return str;
    }

    /**
     * Print face sheet
     */
    private void sendCpcl() {
        //Initialize the cpcl instruction
        CpclCommand cpcl = new CpclCommand();
        //Set sheet height and print copies
        cpcl.addInitializePrinter(1130, 1);
        //Set alignment to center
        cpcl.addJustification(CpclCommand.ALIGNMENT.CENTER);
        //Set font magnification
        cpcl.addSetmag(1, 1);
        //Print text
        cpcl.addText(CpclCommand.TEXT_FONT.FONT_4, 0, 0, 30, "Sample");
        //Set font magnification
        cpcl.addSetmag(0, 0);
        //Set alignment to left
        cpcl.addJustification(CpclCommand.ALIGNMENT.LEFT);
        //Print text
        cpcl.addText(CpclCommand.TEXT_FONT.FONT_4, 0, 0, 65, "Print text");
        cpcl.addText(CpclCommand.TEXT_FONT.FONT_4, 0, 0, 95, "Welcom to use SMARNET printer!");
        cpcl.addText(CpclCommand.TEXT_FONT.FONT_20, 0, 0, 135, "Welcome to the printer!");
        cpcl.addText(CpclCommand.TEXT_FONT.FONT_4, 0, 0, 195, "Smarnet");
        //Set alignment to left
        cpcl.addJustification(CpclCommand.ALIGNMENT.CENTER);
        //Print text
        cpcl.addText(CpclCommand.TEXT_FONT.FONT_4, 0, 0, 195, "Network");
        //Set alignment to right
        cpcl.addJustification(CpclCommand.ALIGNMENT.RIGHT);
        //Print text
        cpcl.addText(CpclCommand.TEXT_FONT.FONT_4, 0, 0, 195, "Device");
        //Set alignment to left
        cpcl.addJustification(CpclCommand.ALIGNMENT.LEFT);
        //Print text
        cpcl.addText(CpclCommand.TEXT_FONT.FONT_4, 0, 0, 230, "Print bitmap!");
        //Print picture
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_scan);
        cpcl.addEGraphics(0, 255, 385, 127, bitmap);
        //Print text
        cpcl.addText(CpclCommand.TEXT_FONT.FONT_4, 0, 0, 645, "Print code128!");
        //Print barcode
        cpcl.addBarcodeText(5, 2);
        cpcl.addBarcode(CpclCommand.COMMAND.BARCODE, CpclCommand.BARCODETYPE.CODE128, 50, 0, 680, "SMARNET");
        cpcl.addText(CpclCommand.TEXT_FONT.FONT_4, 0, 0, 775, "Print QRcode");
        //Print qrcode
        cpcl.addBQrcode(CpclCommand.QRCODE_LEVEL.M, CpclCommand.MODE.A, 0, 810, "QRcode");
        //Set alignment to center
        cpcl.addJustification(CpclCommand.ALIGNMENT.CENTER);
        //Print text
        cpcl.addText(CpclCommand.TEXT_FONT.FONT_4, 0, 0, 1010, "Completed");
        //Set alignment to left
        cpcl.addJustification(CpclCommand.ALIGNMENT.LEFT);
        //Print
        cpcl.addPrint();
        Vector<Byte> datas = cpcl.getCommand();

        // Send cpcl data
        DeviceConnFactoryManager.getDeviceConnFactoryManager().sendDataImmediately(datas);
    }

    /**
     * 打印PDF
     */
    public void printPDF() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                File file = null;
                try {
                    file = new File(mContext.getExternalCacheDir(), "abc.pdf");
                    if (!file.exists()) {
                        InputStream asset = mContext.getAssets().open("abc.pdf");
                        FileOutputStream output = new FileOutputStream(file);
                        final byte[] buffer = new byte[1024];
                        int size;
                        while ((size = asset.read(buffer)) != -1) {
                            output.write(buffer, 0, size);
                        }
                        asset.close();
                        output.close();
                    }
                    MyApplication.printerService.printPDF(file.getAbsolutePath());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    /**
     * 初始化 切纸
     */
    private void firstInit() {
//        threadPool = ThreadPool.getInstantiation();
//        threadPool.addTask(() -> {
//            DeviceConnFactoryManager.getDeviceConnFactoryManager().write("SELFTEST\r\n".getBytes());
//        });
        LabelCommand esc = new LabelCommand();
//        esc.addInitializePrinter();
//        esc.addPrintAndLineFeed();
        // //832 , 1216
        esc.addSize(832, 1216);
//        esc.addReference(832, 1216);
        esc.addCutterBatch();
//        esc.addCutPaper();
        Vector<Byte> datas = esc.getCommand();

        // Send cpcl data
        DeviceConnFactoryManager.getDeviceConnFactoryManager().sendDataImmediately(datas);
    }

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case CONN_STATE_DISCONN:
                    if (DeviceConnFactoryManager.getDeviceConnFactoryManager() != null ||
                            !DeviceConnFactoryManager.getDeviceConnFactoryManager().getConnState()) {
                        DeviceConnFactoryManager.getDeviceConnFactoryManager().closePort();
                        ToastUtil.showToast(getString(R.string.str_disconnect_success));
                    }
                    break;
                case PRINTER_COMMAND_ERROR:
                    ToastUtil.showToast(getString(R.string.str_choice_printer_command));
                    break;
                case CONN_PRINTER:
                    ToastUtil.showToast(getString(R.string.str_cann_printer));
                    break;
            }
        }
    };

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK) {
            switch (requestCode) {

                //Bluetooth connect
                case Constant.BLUETOOTH_REQUEST_CODE: {
                    closePort();
                    //Get bluetooth mac address
                    String macAddress = data.getStringExtra(BluetoothDeviceList.EXTRA_DEVICE_ADDRESS);
                    //Init DeviceConnFactoryManager
                    new DeviceConnFactoryManager.Build()
                            .setConnectMethod(DeviceConnFactoryManager.CONN_METHOD.BLUETOOTH)
                            //Set bluetooth mac address
                            .setMacAddress(macAddress)
                            .build();
                    //Open port
                    threadPool = ThreadPool.getInstantiation();
                    threadPool.addTask(() -> DeviceConnFactoryManager.getDeviceConnFactoryManager().openPort());

                    break;
                }
                case CONN_MOST_DEVICES:
                    if (DeviceConnFactoryManager.getDeviceConnFactoryManager() != null &&
                            DeviceConnFactoryManager.getDeviceConnFactoryManager().getConnState()) {
                        binding.tvConnState.setText(getString(R.string.str_conn_state_connected) + "\n" + getConnDeviceInfo());
                    } else {
                        binding.tvConnState.setText(getString(R.string.str_conn_state_disconnect));
                    }
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * Disconnect
     */
    private void closePort() {
        try {
            if (DeviceConnFactoryManager.getDeviceConnFactoryManager() != null && DeviceConnFactoryManager.getDeviceConnFactoryManager().mPort != null) {
                DeviceConnFactoryManager.getDeviceConnFactoryManager().reader.cancel();
                DeviceConnFactoryManager.getDeviceConnFactoryManager().mPort.closePort();
                DeviceConnFactoryManager.getDeviceConnFactoryManager().mPort = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
